/*
Copyright 2010,2011 Matt Van Der Westhuizen

This file is part of CGLL.

CGLL is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

CGLL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with CGLL.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.chaoticengine.cgll.entity.component.move;

import java.util.Map;
import org.chaoticengine.cgll.entity.component.Command;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.StateBasedGame;

public class TopDownMovementComponent extends BasicMovementComponent {
    /** Acceleration in screen heights per second. */
    protected float accel = 0.0f;

    protected Vector2f accelDir = new Vector2f();

    /** Clipping rectangle to limit movement. */
    protected Rectangle clip = null;

    public TopDownMovementComponent() {
        super();

        commands.put("FORWARD", new Command(this) {
            @Override
            public void doAction(int delta) {
                if (accelDir.y != 1) {
                    accelDir.set(accelDir.x, -1);
                }
            }
        });
        commands.put("BACKWARD", new Command(this) {
            @Override
            public void doAction(int delta) {
                if (accelDir.y != -1) {
                    accelDir.set(accelDir.x, 1);
                }
            }
        });
        commands.put("LEFT", new Command(this) {
            @Override
            public void doAction(int delta) {
                if (accelDir.x != 1) {
                    accelDir.set(-1, accelDir.y);
                }
            }
        });
        commands.put("RIGHT", new Command(this) {
            @Override
            public void doAction(int delta) {
                if (accelDir.x != -1) {
                    accelDir.set(1, accelDir.y);
                }
            }
        });
    }

    @Override
    public void update(GameContainer gc, StateBasedGame sb, int delta) {
        // Enabled commands are triggered, movement executed by BasicMovmentComponent
        super.update(gc, sb, delta);

        // Accellerate
        this.accelerate(accelDir);

        // Apply friction to accelleration
        if (accelDir.length() == 0) {
            if (a.length() != 0) {
                a.scale((1.0f - friction) * (delta / 1000.0f));
            }
        }

        // Reset accelleration direction (to ensure key press / releases are detected)
        accelDir = new Vector2f();

        // Default clipping rectangle is the screen edges
        if (clip == null) {
            clip = new Rectangle(owner.getBounds().getWidth() / 2.0f,
                    owner.getBounds().getHeight() / 2.0f,
                    gc.getWidth(),
                    gc.getHeight());
        }

        // Do clipping
        Vector2f pos = owner.getPosition();
        Shape bounds = owner.getBounds();

        if (pos.getX() + bounds.getWidth() > clip.getMaxX()) {
            pos.set(clip.getMaxX() - bounds.getWidth(), pos.getY());
            v.add(new Vector2f(-v.x, 0.0f));
        } else if (pos.getX() < clip.getMinX()) {
            pos.set(clip.getMinX(), pos.getY());
            v.add(new Vector2f(-v.x, 0.0f));
        }

        if (pos.getY() + bounds.getHeight() > clip.getMaxY()) {
            pos.set(pos.getX(), clip.getMaxY() - bounds.getHeight());
            v.add(new Vector2f(0.0f, -v.y));
        } else if (pos.getY() < clip.getMinY()) {
            pos.set(pos.getX(), clip.getMinY());
            v.add(new Vector2f(0.0f, -v.y));
        }

        owner.setPosition(pos);
    }

    @Override
    public Map<String, Command> getCommands() {
        return (commands);
    }
    
    public Rectangle getClip() {
        return(this.clip);
    }

    public void setClip(Rectangle r) {
        this.clip = r;
    }
}